package cn.cosmosx.base.encrypt.jwt;

import cn.cosmosx.base.exception.PlatformException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Calendar;

/**
 * JWT工具类
 * 基于 com.auth0
 */
@Slf4j
public final class JWTUtil {

    /**
     * 加密秘钥
     */
    private final static String PRIVATE_KEY = "spring@spring-boot-security@Jwt@Project-QuickSand@Author-gengzhy";
    /**
     * 签发人
     */
    private final static String ISSUER = "gengzhy";


    /**
     * 创建JWT Token
     * @param id - 唯一标识（用户id等）
     */
    public static String token(String id) {
        try {
            return JWT.create()
                    .withSubject(id)
                    .withIssuer(ISSUER)
                    .withIssuedAt(Calendar.getInstance().getTime())
                    .sign(Algorithm.HMAC256(PRIVATE_KEY));
        } catch (Exception e) {
            log.error("Token生成失败", e);
            throw new PlatformException("Token生成失败");
        }
    }

    /**
     * 创建JWT Token
     */
    public static String token(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
        return JWT.create().sign(Algorithm.RSA256(publicKey, privateKey));
    }

    /**
     * JWT Token校验
     *
     */
    public static DecodedJWT verify(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(PRIVATE_KEY);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(ISSUER)
                    .build();
            return verifier.verify(token);
        } catch (TokenExpiredException e) {
            log.error("Token 过期", e);
            throw new TokenExpiredException("Token 过期", e.getExpiredOn());
        } catch (JWTVerificationException e) {
            log.error("Token 验证失败", e);
            throw new JWTVerificationException("Token 验证失败");
        }
    }

}
